import { UIView } from "./UIView";
import ResManager from "../ResManager";
import { ProgressHandle } from "../../utils/Utils";
import { UICF, UIID } from "./UIConst";

/**
 * UIManager界面管理类
 * 
 * 1.打开界面，根据配置自动加载界面、调用初始化、播放打开动画、隐藏其他界面、屏蔽下方界面点击
 * 2.关闭界面，根据配置自动关闭界面、播放关闭动画、恢复其他界面
 * 3.切换界面，与打开界面类似，但是是将当前栈顶的界面切换成新的界面（先关闭再打开）
 * 4.提供界面缓存功能
 * 
 */
export class UIManager {
    private constructor() { }
    private static _instance: UIManager;
    public static get instance() {
        if (!this._instance) {
            this._instance = new UIManager();
            this._instance.rootNode = cc.director.getScene().children[0].getChildByName('root');
            cc.game.addPersistRootNode(this._instance.rootNode);
        }
        return this._instance;
    }
    public rootNode: cc.Node = null;
    private zIndex = 200;
    private UICache: Map<UIID, UIView> = new Map<UIID, UIView>();
    private stack: Array<UIView> = [];
    public async loadUI(uiId: number, onProgress?: ProgressHandle) {
        await this.getOrCreateUI(uiId, onProgress);
    }

    private async getOrCreateUI(uiId: number, onProgress?: ProgressHandle) {
        return new Promise<UIView>((resolve, reject) => {
            let uiView: UIView = this.UICache[uiId];
            if (uiView) {
                resolve(uiView);
                return;
            }
            let uiPath = UICF[uiId].prefab;
            if (null == uiPath) {
                cc.log(`getOrCreateUI ${uiId} faile, prefab conf not found!`);
                reject();
                return;
            }
            ResManager.instance.load(uiPath, onProgress, (err: Error, prefab: cc.Prefab) => {
                // 检查加载资源错误
                if (err) {
                    cc.log(`getOrCreateUI loadRes ${uiId} faile, path: ${uiPath} error: ${err}`);
                    reject();
                    return;
                }
                // 检查实例化错误
                let uiNode: cc.Node = cc.instantiate(prefab);

                // 检查组件获取错误
                uiView = uiNode.getComponent(UIView);
                if (null == uiView) {
                    cc.log(`getOrCreateUI getComponent ${uiId} faile, path: ${uiPath}`);
                    uiNode.destroy();
                    ResManager.instance.releaseAsset(prefab);
                    reject();
                    return;
                }
                this.UICache[uiId] = uiView;
                this.rootNode.children[UICF[uiId].level].addChild(uiNode);
               
                resolve(uiView);
                return;
            });
        })

    }
    public addUI(uiView: UIView) {
        this.UICache[uiView.UIid] = uiView;
        if (uiView.isOpen) {
            this.stack.push(uiView);
        }
    }
    public getUI(uiId: number): UIView {
        return this.UICache[uiId];
    }
    /** 打开界面并添加到界面栈中 */
    public async open(uiId: number, ...uiArgs) {
        let uiView = await this.getOrCreateUI(uiId);
        if (!uiView) {
            console.error(`无法打开：${UIID[uiId]}`);
            return;
        }
        uiView.UIid = uiId;
        this.stack.push(uiView);
        uiView.node.zIndex = this.zIndex;
        this.zIndex++;
        let adNode = uiView.adNode;
        
        uiView.isOpen = true;
        uiView.onOpen(...uiArgs);
    }
    /**
     * 关闭当前界面
     * @param uiView 要关闭的界面
     */
    public close(uiView: UIView) {
        if (!uiView) {
            console.error('uiView为空');
            return;
        }
        let index = this.stack.indexOf(uiView);
        if (index != -1) {
            this.stack.splice(index, 1);
        }
        uiView.isOpen = false;
        uiView.onClose();
    }
    public destroyAll() {
        this.UICache.forEach((value, key, map) => {
            value.node.destroy();
            ResManager.instance.release(UICF[value.UIid].prefab);
        });
        this.stack = null;
        this.UICache = null;
    }
    public destroy(uiView: UIView) {
        uiView.node.destroy();
        this.UICache.delete(uiView.UIid);
        let index = this.stack.indexOf(uiView);
        if (index != -1)
            this.stack.splice(index, 1);
        ResManager.instance.release(UICF[uiView.UIid].prefab);
    }

    public showToast(text: string) {
            this.open(UIID.UIToast, text);
    }
    /** 清理界面缓存 */
    public clearCache(): void {
        for (const key in this.UICache) {
            let ui = this.UICache[key];
            if (cc.isValid(ui.node)) {
                if (cc.isValid(ui)) {
                    ui.releaseAutoRes();
                }
                ui.node.destroy();
            }
        }
    }

}